package com.it.schoolhomeos.service.impl;

import com.it.schoolhomeos.dto.UserDTO;
import com.it.schoolhomeos.entity.User;
import com.it.schoolhomeos.enums.Role;
import com.it.schoolhomeos.repository.UserRepository;
import com.it.schoolhomeos.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * UserService接口的实现类
 * 
 * 实现用户相关的业务逻辑
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    /**
     * 用户登录
     * 
     * @param username 用户名
     * @param password 密码
     * @return 登录成功的用户DTO对象
     * @throws RuntimeException 如果用户名或密码错误
     */
    @Override
    public UserDTO login(String username, String password) {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户名或密码错误"));
        
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new RuntimeException("用户名或密码错误");
        }
        
        if (!user.getEnabled()) {
            throw new RuntimeException("账号已被禁用");
        }
        
        return convertToDTO(user);
    }
    
    /**
     * 获取当前登录用户信息
     * 
     * @return 当前登录用户的DTO对象
     * @throws RuntimeException 如果用户未登录
     */
    @Override
    public UserDTO getCurrentUser() {
        // 从SecurityContextHolder获取当前用户
        org.springframework.security.core.Authentication authentication = 
            org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication();
        
        if (authentication == null || !authentication.isAuthenticated() || 
            "anonymousUser".equals(authentication.getPrincipal())) {
            throw new RuntimeException("用户未登录");
        }
        
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        return convertToDTO(user);
    }
    
    /**
     * 根据ID获取用户信息
     * 
     * @param id 用户ID
     * @return 用户DTO对象
     * @throws RuntimeException 如果用户不存在
     */
    @Override
    public UserDTO getUserById(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        return convertToDTO(user);
    }
    
    /**
     * 根据角色获取用户列表
     * 
     * @param role 用户角色
     * @return 指定角色的用户DTO列表
     */
    @Override
    public List<UserDTO> getUsersByRole(String roleStr) {
        Role role = Role.valueOf(roleStr);
        return userRepository.findByRole(role)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 创建新用户
     * 
     * @param user 用户实体对象
     * @return 创建成功的用户DTO对象
     * @throws RuntimeException 如果用户名已存在
     */
    @Override
    public UserDTO createUser(User user) {
        if (user.getId() != null) {
            throw new RuntimeException("创建用户不应该包含ID");
        }
        
        if (existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setEnabled(true);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        User savedUser = userRepository.save(user);
        return convertToDTO(savedUser);
    }
    
    /**
     * 更新用户信息
     * 
     * @param user 用户实体对象
     * @return 更新后的用户DTO对象
     * @throws RuntimeException 如果用户不存在
     */
    @Override
    public UserDTO updateUser(User user) {
        if (user.getId() == null) {
            throw new RuntimeException("更新用户必须包含ID");
        }
        
        User existingUser = userRepository.findById(user.getId())
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        if (!existingUser.getUsername().equals(user.getUsername()) 
                && existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        if (StringUtils.hasText(user.getPassword())) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        } else {
            user.setPassword(existingUser.getPassword());
        }
        
        user.setCreateTime(existingUser.getCreateTime());
        user.setUpdateTime(LocalDateTime.now());
        
        User updatedUser = userRepository.save(user);
        return convertToDTO(updatedUser);
    }
    
    /**
     * 删除用户
     * 
     * @param id 用户ID
     * @throws RuntimeException 如果用户不存在
     */
    @Override
    public void deleteUser(Long id) {
        if (!userRepository.existsById(id)) {
            throw new RuntimeException("用户不存在");
        }
        userRepository.deleteById(id);
    }
    
    /**
     * 检查用户名是否已存在
     * 
     * @param username 用户名
     * @return 如果用户名已存在则返回true，否则返回false
     */
    @Override
    public boolean existsByUsername(String username) {
        return userRepository.existsByUsername(username);
    }
    
    /**
     * 将User实体转换为UserDTO
     * 
     * @param user User实体
     * @return UserDTO对象
     */
    private UserDTO convertToDTO(User user) {
        UserDTO dto = new UserDTO();
        dto.setId(user.getId());
        dto.setUsername(user.getUsername());
        dto.setName(user.getName());
        dto.setPhone(user.getPhone());
        dto.setEmail(user.getEmail());
        dto.setAvatar(user.getAvatar());
        dto.setRole(user.getRole().name());
        dto.setEnabled(user.getEnabled());
        dto.setCreateTime(user.getCreateTime());
        dto.setUpdateTime(user.getUpdateTime());
        return dto;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("用户不存在: " + username));
        return org.springframework.security.core.userdetails.User
                .withUsername(user.getUsername())
                .password(user.getPassword())
                .roles(user.getRole().name())
                .build();
    }

    @Override
    public User findByUsername(String username) {
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
    }

    @Override
    public Page<User> findParents(int page, int size, String keyword) {
        PageRequest pageRequest = PageRequest.of(page, size, Sort.by("createTime").descending());
        if (StringUtils.hasText(keyword)) {
            return userRepository.findByRoleAndUsernameContainingOrNameContaining(
                    Role.PARENT, keyword, keyword, pageRequest);
        }
        return userRepository.findByRole(Role.PARENT, pageRequest);
    }

    @Override
    public User findParentById(Long id) {
        Optional<User> userOpt = userRepository.findById(id);
        if (userOpt.isEmpty()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        if (user.getRole() != Role.PARENT) {
            throw new RuntimeException("该用户不是家长");
        }
        
        return user;
    }

    @Override
    public User createParent(User user) {
        if (user.getId() != null) {
            throw new RuntimeException("创建用户不应该包含ID");
        }
        if (existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        user.setRole(Role.PARENT);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setEnabled(true);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        return userRepository.save(user);
    }

    @Override
    public User updateParent(User user) {
        if (user.getId() == null) {
            throw new RuntimeException("更新用户必须包含ID");
        }
        
        User existingUser = findParentById(user.getId());
        
        // 如果前端没有传username，则使用已存在用户的username
        if (user.getUsername() == null || user.getUsername().trim().isEmpty()) {
            user.setUsername(existingUser.getUsername());
        } else if (!existingUser.getUsername().equals(user.getUsername()) 
                && existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        user.setRole(Role.PARENT);
        if (StringUtils.hasText(user.getPassword())) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        } else {
            user.setPassword(existingUser.getPassword());
        }
        user.setEnabled(true);
        user.setCreateTime(existingUser.getCreateTime());
        user.setUpdateTime(LocalDateTime.now());
        
        return userRepository.save(user);
    }

    @Override
    public void deleteParent(Long id) {
        userRepository.deleteById(id);
    }

    @Override
    public List<User> findAllParents() {
        return userRepository.findByRole(Role.PARENT);
    }

    @Override
    public Page<User> findTeachers(int page, int size, String keyword) {
        PageRequest pageRequest = PageRequest.of(page, size, Sort.by("createTime").descending());
        if (StringUtils.hasText(keyword)) {
            return userRepository.findByRoleAndUsernameContainingOrNameContaining(
                    Role.TEACHER, keyword, keyword, pageRequest);
        }
        return userRepository.findByRole(Role.TEACHER, pageRequest);
    }

    @Override
    public User findTeacherById(Long id) {
        Optional<User> userOpt = userRepository.findById(id);
        if (userOpt.isEmpty()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        if (user.getRole() != Role.TEACHER) {
            throw new RuntimeException("该用户不是教师");
        }
        
        return user;
    }

    @Override
    public User createTeacher(User user) {
        if (user.getId() != null) {
            throw new RuntimeException("创建用户不应该包含ID");
        }
        if (existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        user.setRole(Role.TEACHER);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setEnabled(true);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        return userRepository.save(user);
    }

    @Override
    public User updateTeacher(User user) {
        if (user.getId() == null) {
            throw new RuntimeException("更新用户必须包含ID");
        }
        
        User existingUser = findTeacherById(user.getId());
        
        if (!existingUser.getUsername().equals(user.getUsername()) 
                && existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        user.setRole(Role.TEACHER);
        if (StringUtils.hasText(user.getPassword())) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        } else {
            user.setPassword(existingUser.getPassword());
        }
        user.setEnabled(true);
        user.setCreateTime(existingUser.getCreateTime());
        user.setUpdateTime(LocalDateTime.now());
        
        return userRepository.save(user);
    }

    @Override
    public void deleteTeacher(Long id) {
        User user = findTeacherById(id);
        userRepository.delete(user);
    }

    @Override
    public Page<User> findAdmins(int page, int size, String keyword) {
        PageRequest pageRequest = PageRequest.of(page, size, Sort.by("createTime").descending());
        if (StringUtils.hasText(keyword)) {
            return userRepository.findByRoleAndUsernameContainingOrNameContaining(
                    Role.ADMIN, keyword, keyword, pageRequest);
        }
        return userRepository.findByRole(Role.ADMIN, pageRequest);
    }

    @Override
    public User findAdminById(Long id) {
        Optional<User> userOpt = userRepository.findById(id);
        if (userOpt.isEmpty()) {
            throw new RuntimeException("用户不存在");
        }
        
        User user = userOpt.get();
        if (user.getRole() != Role.ADMIN) {
            throw new RuntimeException("该用户不是管理员");
        }
        
        return user;
    }

    @Override
    public User createAdmin(User user) {
        if (user.getId() != null) {
            throw new RuntimeException("创建用户不应该包含ID");
        }
        if (existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        user.setRole(Role.ADMIN);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setEnabled(true);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        return userRepository.save(user);
    }

    @Override
    public User updateAdmin(User user) {
        if (user.getId() == null) {
            throw new RuntimeException("更新用户必须包含ID");
        }
        
        User existingUser = findAdminById(user.getId());
        
        if (!existingUser.getUsername().equals(user.getUsername()) 
                && existsByUsername(user.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        user.setRole(Role.ADMIN);
        if (StringUtils.hasText(user.getPassword())) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        } else {
            user.setPassword(existingUser.getPassword());
        }
        user.setEnabled(true);
        user.setCreateTime(existingUser.getCreateTime());
        user.setUpdateTime(LocalDateTime.now());
        
        return userRepository.save(user);
    }

    @Override
    public void deleteAdmin(Long id) {
        User user = findAdminById(id);
        userRepository.delete(user);
    }

    @Override
    public UserDTO updateProfile(User user) {
        // 获取当前登录用户
        UserDTO currentUser = getCurrentUser();
        if (currentUser == null) {
            throw new RuntimeException("用户未登录");
        }
        
        // 获取数据库中的用户信息
        User existingUser = findByUsername(currentUser.getUsername());
        
        // 只允许修改部分信息
        existingUser.setName(user.getName());
        existingUser.setPhone(user.getPhone());
        existingUser.setEmail(user.getEmail());
        existingUser.setUpdateTime(LocalDateTime.now());
        
        User updatedUser = userRepository.save(existingUser);
        return convertToDTO(updatedUser);
    }

    @Override
    public void changePassword(String oldPassword, String newPassword) {
        // 获取当前登录用户
        UserDTO currentUser = getCurrentUser();
        if (currentUser == null) {
            throw new RuntimeException("用户未登录");
        }
        
        // 获取数据库中的用户信息
        User existingUser = findByUsername(currentUser.getUsername());
        
        // 验证旧密码
        if (!passwordEncoder.matches(oldPassword, existingUser.getPassword())) {
            throw new RuntimeException("旧密码错误");
        }
        
        // 更新密码
        String encodedPassword = passwordEncoder.encode(newPassword);
        existingUser.setPassword(encodedPassword);
        existingUser.setUpdateTime(LocalDateTime.now());
        
        // 保存更新
        User savedUser = userRepository.save(existingUser);
        
        // 验证密码是否成功更新
        if (!passwordEncoder.matches(newPassword, savedUser.getPassword())) {
            throw new RuntimeException("密码更新失败，请联系管理员");
        }
    }

    @Override
    public void updateAvatar(String avatarUrl) {
        // 获取当前登录用户
        UserDTO currentUser = getCurrentUser();
        if (currentUser == null) {
            throw new RuntimeException("用户未登录");
        }
        
        // 获取数据库中的用户信息
        User existingUser = findByUsername(currentUser.getUsername());
        
        // 更新头像
        existingUser.setAvatar(avatarUrl);
        existingUser.setUpdateTime(LocalDateTime.now());
        
        userRepository.save(existingUser);
    }
} 